﻿//
//SpingManager.cs for unity-chan!
//
//Original Script is here:
//ricopin / SpingManager.cs
//Rocket Jump : http://rocketjump.skr.jp/unity3d/109/
//https://twitter.com/ricopin416
//
//Revised by N.Kobayashi 2014/06/24
//           Y.Ebata
//
using UnityEngine;
using System.Collections;

namespace UnityChan
{
    public class SpringManager0 : MonoBehaviour
    {
        //Kobayashi
        // DynamicRatio is paramater for activated level of dynamic animation 
        public float dynamicRatio = 1.0f;

        //Ebata
        public float stiffnessForce;
        public AnimationCurve stiffnessCurve;
        public float dragForce;
        public AnimationCurve dragCurve;
        public SpringBone0[] springBones;
        public SpringBone[] springBonesNew;
        public bool bNew;
        public SpringCollider[] coliders;
        public SpringCollider[] coliders2;
        public float radius;
        public Vector3 boneAxis = Vector3.up;
        public bool calAxis;

        [ContextMenu("GetFromNewMgrAndAddOld")]
        void GetFromNewMgrAndAddOld()
        {

            springBonesNew = GetComponent<SpringManager>().springBones;

            var n = new System.Collections.Generic.List<SpringBone0>();
            foreach (var bone in springBonesNew)
            {
                n.Add(bone.GetComOrAdd<SpringBone0>());
            }
            springBones = n.ToArray();
            Apply();
        }
        [ContextMenu("GetBonesNew")]
        void GetBonesNew()
        {
            var n = new System.Collections.Generic.List<SpringBone>();
            foreach (var bone in springBones)
            {
                n.Add(bone.GetComponent<SpringBone>());
            }
            springBonesNew = n.ToArray();
        }

        public void Apply()
        {
            foreach (var bone in springBones)
            {
                bone.child = bone.transform.GetChild(0);

                if (calAxis)bone.boneAxis = bone.child.localPosition.normalized;
                else bone.boneAxis = boneAxis;
                if ((bone.name.IndexOf(".r") != -1 || bone.name.IndexOf(".l") != -1) == false)
                {
                    bone.colliders = coliders2;
                }
                else
                {
                    bone.colliders = coliders;
                }
                bone.radius = radius;
            }
        }

        void Start()
        {
            UpdateParameters();
        }

#if UNITY_EDITOR
        void Update()
        {

            //Kobayashi
            if (dynamicRatio >= 1.0f)
                dynamicRatio = 1.0f;
            else if (dynamicRatio <= 0.0f)
                dynamicRatio = 0.0f;
            //Ebata
            UpdateParameters();

        }
#endif
        private void LateUpdate()
        {
            //Kobayashi
            if (dynamicRatio != 0.0f)
            {
                if (bNew)
                {
                    for (int i = 0; i < springBonesNew.Length; i++)
                    {
                        if (dynamicRatio > springBonesNew[i].threshold)
                        {
                            springBonesNew[i].UpdateSpring();
                        }
                    }
                }
                else
                {
                    for (int i = 0; i < springBones.Length; i++)
                    {
                        if (dynamicRatio > springBones[i].threshold)
                        {
                            springBones[i].UpdateSpring();
                        }
                    }
                }
            }
        }

        private void UpdateParameters()
        {
            UpdateStiffnessForce(stiffnessForce, stiffnessCurve);
            UpdateDragForce(dragForce, dragCurve);
        }
        private void UpdateStiffnessForce(float baseValue, AnimationCurve curve)
        {
            var start = curve.keys[0].time;
            var end = curve.keys[curve.length - 1].time;
            for (int i = 0; i < springBones.Length; i++)
            {
                if (!springBones[i].isUseEachBoneForceSettings)
                {
                    var scale = curve.Evaluate(start + (end - start) * i / (springBones.Length - 1));
                    springBones[i].stiffnessForce = baseValue * scale;
                }
            }
        }
        private void UpdateDragForce(float baseValue, AnimationCurve curve)
        {
            var start = curve.keys[0].time;
            var end = curve.keys[curve.length - 1].time;
            for (int i = 0; i < springBones.Length; i++)
            {
                if (!springBones[i].isUseEachBoneForceSettings)
                {
                    var scale = curve.Evaluate(start + (end - start) * i / (springBones.Length - 1));
                    springBones[i].dragForce = baseValue * scale;
                }
            }
        }
        private void UpdateParameterEditoVer(string fieldName, float baseValue, AnimationCurve curve)
        {
#if UNITY_EDITOR
            var start = curve.keys[0].time;
            var end = curve.keys[curve.length - 1].time;
            //var step	= (end - start) / (springBones.Length - 1);

            var prop = springBones[0].GetType().GetField(fieldName, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);

            for (int i = 0; i < springBones.Length; i++)
            {
                //Kobayashi
                if (!springBones[i].isUseEachBoneForceSettings)
                {
                    var scale = curve.Evaluate(start + (end - start) * i / (springBones.Length - 1));
                    prop.SetValue(springBones[i], baseValue * scale);
                }
            }
#endif
        }
    }
}